﻿using System;
using System.Collections.Generic;
using log4net;

namespace Bambit.XmlRpc.Dispatcher
{

	/// <summary>
	/// Standard delegate for methods registered with the <see cref="RpcDispatcher">dispatcher</see>
	/// </summary>
	public delegate MethodResponse DispatchMethod(IList<Parameter> parameters);

	public class RpcDispatcher :Dictionary<string, DispatchMethod> 
	{
// ReSharper disable InconsistentNaming
		private static readonly ILog _Logger = LogManager.GetLogger(typeof (RpcDispatcher));
// ReSharper restore InconsistentNaming

		/// <summary>
		/// Attempts to dispatches the specified method call.
		/// </summary>
		/// <param name="methodCall">The method call to dispatch.</param>
		/// <returns>A <see cref="MethodResponse"/> either containing <see cref="Fault"/> information or
		/// the return from the dispatched method</returns>
		public MethodResponse Dispatch(MethodCall methodCall)
		{
			MethodResponse methodResponse;
			if(ContainsKey(methodCall.MethodName))
			{
				try
				{
					methodResponse = this[methodCall.MethodName](methodCall.Parameters);
				}
				catch (Exception exc)
				{
					_Logger.Error(
						string.Format("An exception was thrown while trying to execute the method call {0}", methodCall.MethodName), exc);
					methodResponse=new MethodResponse
					               	{
					               		Fault = Fault.CreateFault(-1,
					               		                          string.Format("An exception was thrown during execution: {0}",
					               		                                        exc.Message))
					               	};
				}
			}
			else
			{
				methodResponse = new MethodResponse
				                 	{
				                 		Fault =
				                 			Fault.CreateFault(-2,string.Format("Could not dispatch method {0}: No such method registered",
				                 			                  methodCall.MethodName))
				                 	};
			}
			return methodResponse;
		}
	}
}
